package com.gopay.checkorder.service.task;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.dao.BisBankOrderQueryDAO;
import com.gopay.checkorder.manager.BankOrderManager;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.alarm.OrderAlarmDataCollector;
import com.gopay.checkorder.service.alarm.OrderAlarmRecordStorage;
import com.gopay.checkorder.service.task.thread.CheckOrderTaskThread;
import com.gopay.checkorder.service.task.thread.CheckOrderThread;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.util.ExecutorUtil;
import com.gopay.common.util.spring.SpringContextUtil;

/**
 * 对单Task
 * 
 * @CheckOrderTask.java
 * @author yaobo
 * @2013-3-21 上午10:54:27 www.gopay.com.cn Inc.All rights reserved.
 */
public class CheckOrderPerHourTaskImpl implements Task {
    
	private final static Logger logger = LoggerFactory.getLogger("CHECK_ORDER");

	private final static int MAX_SIZE = 10000;

	@Resource(name = "bisBankOrderQueryDAO")
    private BisBankOrderQueryDAO bisBankOrderQueryDAO;

    @Resource(name = "checkOrderTaskThread")
    private CheckOrderTaskThread checkOrderTaskThread;
    
    @Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;
    
    @Resource(name = "orderAlarmRecordStorage")
    private OrderAlarmRecordStorage orderAlarmRecordStorage;
    
    private String bank;
    
    private final static int THREAD_SIZE = 10;
    private ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_SIZE);

    private void printLog(StopWatch sw,String bank,String prefix){
        sw.split();
        logger.error(prefix+"------,bank="+bank+",耗时="+sw.getSplitTime());
    }

    /**
     * 任务执行
     */
    public void doTask() {
        try{
            StopWatch sw=new StopWatch();
            sw.start();
            printLog(sw,bank,"CheckOrderPerHourTaskImpl------start");
            
	        int pageSize = 100;
	        int pageIndex = 1;
	        int count = 0;
	
	        checkBefore();
	        Date date = new Date();
	        int resCount = getCheckOrderCount(date);
	        printLog(sw,bank,"CheckOrderPerHourTaskImpl------对单总数量="+resCount);
	        
	        //订单对账报警采集者
	        OrderAlarmDataCollector alarmCollector=new OrderAlarmDataCollector();
	        
	        List<BankOrder> list = null;
	        while (count < resCount) {
	            list = getCheckOrder(date, pageIndex, pageSize);
	            if (list == null || list.size() == 0) {
	                printLog(sw,bank,"CheckOrderPerHourTaskImpl------分页为空，跳出while循环");
	                break;
	            }
	            printLog(sw,bank,"CheckOrderPerHourTaskImpl------list.size()="+list.size()+",pageIndex="+pageIndex);
	

	            //订单队列	            
	            ConcurrentLinkedQueue<BankOrder> queue=new ConcurrentLinkedQueue<BankOrder>();
	            queue.addAll(list);
	
	            //同步锁存器
	            CountDownLatch latch = new CountDownLatch(queue.size());
	            
	            //线程池中线程全部参与
	            for(int i=0;i<THREAD_SIZE;i++){
	                CheckOrderThread thread=new CheckOrderThread(bankOrderService,queue,latch,alarmCollector);
	                threadPool.execute(thread);
	                 
	            }
	            
	            // 同步锁存器等待所有线程执行完成
                if(!latch.await(118, TimeUnit.SECONDS)){
                    logger.error("同步锁存器等待超时了 latch.count=" + latch.getCount());
                    threadPool.awaitTermination(1, TimeUnit.SECONDS);
                }

	
	            count += pageSize;
	            pageIndex++;
	
	        }
	        
	        printLog(sw,bank,"CheckOrderPerHourTaskImpl------结束while循环,resCount="+resCount);
	        
	        //判断报警阈值并保存报警记录
	        orderAlarmRecordStorage.store(alarmCollector);
	        
	        printLog(sw,bank,"CheckOrderPerHourTaskImpl------end");
	        sw.stop();
	        
        }catch (Throwable t) {
        	logger.error("执行对单Task时出现异常" ,t);
		}      
    }
    
    /**
     * 
     */
    private void checkBefore() {
	}

	/**
     * 待对账订单笔数
     * @param orderStatus
     * @param totalCheckTimes
     * @return
     */
    protected int getCheckOrderCount(Date date){
    	int resCount =0;
    	if(StringUtils.isNotBlank(bank)){
    	    resCount=bisBankOrderQueryDAO.getCheckOrderCountByBank(date, bank);
    	}else{
    	    resCount=bisBankOrderQueryDAO.getCheckOrderCount(date);
    	}
    	
        if (resCount > MAX_SIZE) {
            resCount = MAX_SIZE;
        }
        return resCount;
    }
    
    /**
     * 分页查询对账记录
     * @param orderStatus
     * @param totalCheckTimes
     * @param pageIndex
     * @param pageSize
     * @return
     */
    protected List<BankOrder> getCheckOrder(Date date, int pageIndex, int pageSize){
        if(StringUtils.isNotBlank(bank)){
            return bisBankOrderQueryDAO.getCheckOrderByBank(date, pageIndex, pageSize, bank);
        }else{
            return bisBankOrderQueryDAO.getCheckOrder(date, pageIndex, pageSize);
        }
    }
    
    public void setBank(String bank) {
        this.bank = bank;
    }
    
   
}